package com.topisv.tms.task.interfacetask;

import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.topisv.tms.entity.interfacetask.InterfaceTask;
import com.topisv.tms.entity.interfacetask.InterfaceTaskEnum;
import com.topisv.tms.service.interfacetask.InterfaceTaskProcessService;
import com.topisv.tms.service.interfacetask.InterfaceTaskService;
import com.topisv.tms.slf4j.MarkerConstant;

/**
 * 接口任务处理
 * @author <a href="mailto:yuanlianghe@nryuncang.com">yuanlianghe</a>
 */
@Component
@Lazy(false)
public class InterfaceTaskProcessProvider implements InitializingBean {

    private static final Logger logger = LoggerFactory.getLogger(InterfaceTaskProcessProvider.class);
    @Autowired
    private InterfaceTaskService taskService;
    @Autowired
    private InterfaceTaskProcessService taskProcessService;
    
    private BlockingQueue<InterfaceTask> taskQueue = new ArrayBlockingQueue<InterfaceTask>(2000);
    
    private String node;
    
    private int MAX_ROWS = 500;
    private int THREAD_CNT = 4; //注：如果大于1， 可能会出现多次消费的情况。取决于接口发送的速度。(此问题已解决2016.11.11)
    
    public static final ConcurrentMap<Long, Integer> PROCESSING_MAP = new ConcurrentHashMap<Long, Integer>(2000);
    
    
    //每隔一分钟取次任务数据
    @Scheduled(cron = "0/59 * * * * *")
    public void execute() {
        try {
            int cnt = taskService.lockTask(getNode(), InterfaceTaskEnum.STATUS_READY, MAX_ROWS);
            
            int ok = 0;
            //注： 这里只查找未从发送过接口的数据，原因：失败的接口，在原有的发送方法中会自动写表，然后job重发
            List<InterfaceTask> taskList = taskService.findTask(InterfaceTaskEnum.STATUS_READY, getNode(), 0, MAX_ROWS);
            for (InterfaceTask task : taskList) {
                if (!taskQueue.contains(task)) {
                    boolean flag = taskQueue.offer(task);
                    if (flag) {
                        ok++;
                    }
                }
            }
            
            logger.info(MarkerConstant.MONITOR_MARKE, "接口任务锁定,当前队列:{}, 本次锁定:{},成功加入:{}", taskQueue.size(), cnt, ok);
            
        } catch (Exception ex) {
            logger.error("接口任务InterfaceTaskProcessProvider case some error, please check soon.", ex);
        }
    }
    
    
    public String getNode() {
        if (node == null) {
            String name = ManagementFactory.getRuntimeMXBean().getName();
            node = name.substring(name.indexOf("@") + 1);
        }
        return node;
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        while (THREAD_CNT-- > 0) {
            new InterfaceTaskProcessWorker("接口任务第" + (THREAD_CNT + 1), taskQueue, taskService, taskProcessService).start();
        }
    }
}
